# coding:utf-8
# https://www.cnblogs.com/zhiyiYo/p/15676079.html
import os
import sys
import time

import resources.resource_rc
from PyQt5.QtCore import QRect, QRectF, QSize, Qt, QCoreApplication, pyqtSignal, QPoint, QDir, QTimer, QEvent
from PyQt5.QtGui import QPainter, QPixmap, QWheelEvent, QKeySequence, QPen, QBrush, QTransform, QFont, QTouchEvent, \
    QPainterPath, QColor
from PyQt5.QtWidgets import (QApplication, QGraphicsItem, QGraphicsPixmapItem,
                             QGraphicsScene, QGraphicsView, QShortcut, QFileDialog, QGraphicsRectItem,
                             QGraphicsLineItem, QGraphicsSimpleTextItem, QGraphicsPathItem, QGraphicsEllipseItem)
from utils.pictureHandlers import PicturesReader


#############################################################
# moveTo()函数隐式启动一个新的子路径，并关闭前一个子路径。
# 另一种启动新子路径的方法是调用closeSubpath()函数，该函数通过将currentPosition()中的一行添加回路径的起始位置来关闭当前路径。
# 请注意，新路径将具有（0,0）作为其初始currentPosition()。
#############################################################


class MultiTouchWindow(QGraphicsView):
    """ 图片查看器 """

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        # 快捷键
        self.ShortcutFun()
        self.setToolTip('全屏与退出全屏：\n               双击 或者 F11')
        # 初始化小部件
        self.__initWidget()
        # 画图初始化
        self.DrawInit()

    def ShortcutFun(self):
        # 快捷键 F11
        # 全屏
        self.screenStatus = 'Normal'
        screenShortcut = QShortcut(QKeySequence(Qt.Key_F11), self)
        screenShortcut.activated.connect(self.WindowSizeFun)
        # 快捷键 F5
        screenShortcut2 = QShortcut(QKeySequence(Qt.Key_F5), self)
        screenShortcut2.activated.connect(self.CleanFun)

    def CleanFun(self):
        self.graphicsScene.clear()
        # 画图初始化
        self.DrawInit()

    def WindowSizeFun(self):
        # print(toStatus)
        if self.screenStatus == 'Normal':
            self.showFullScreen()
            self.screenStatus = 'FullScreen'
        else:
            self.showNormal()
            self.screenStatus = 'Normal'

    def __initWidget(self):
        """ 初始化小部件 """
        self.resize(1800, 1200)
        # 隐藏滚动条
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        # 以鼠标所在位置为锚点进行缩放
        self.setTransformationAnchor(self.AnchorUnderMouse)

        # 平滑缩放
        # self.pixmapItem.setTransformationMode(Qt.SmoothTransformation)
        self.setRenderHints(QPainter.Antialiasing |
                            QPainter.SmoothPixmapTransform)

        # 设置场景
        # self.graphicsScene.addItem(self.pixmapItem)
        # 创建场景
        self.graphicsScene = QGraphicsScene()
        self.graphicsScene.clearSelection()  # 【清除选择】
        self.setScene(self.graphicsScene)
        self.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.setSceneRect(0, 0, 1800, 1200)  # fix scene size 500 500
        self.setRenderHint(QPainter.Antialiasing)  ##设置视图的抗锯齿渲染模式。

        # 通过图标
        self.pixmapRi = QPixmap(':/icons/icons/right.png')
        self.pixmapItemRi = QGraphicsPixmapItem(self.pixmapRi)
        self.pixmapItemRi.setScale(0.1)
        self.pixmapItemRi.setPos(self.width() / 2, self.height() / 2)
        self.pixmapItemRi.setVisible(False)
        self.graphicsScene.addItem(self.pixmapItemRi)

    def DrawInit(self):
        self.colorList = [Qt.yellow, Qt.red, Qt.green, Qt.blue, Qt.magenta, Qt.darkGreen, Qt.color1, Qt.cyan, Qt.gray,
                          Qt.darkRed, Qt.darkBlue]

        self.cycleRadius = 60
        self.pathPenWidth = 9
        # 触摸Id记录
        self.touchIdList = set()
        # 触摸点ID 与 颜色绑定 列表
        self.pIdAndColorList = []

        # 提示文字
        self.tipViewText = QGraphicsSimpleTextItem('全屏与退出全屏：\n               F11')
        self.tipViewText.setPen(QPen(Qt.gray))
        # tipViewText.setPos(self.myConfig.screenLength / 8, self.myConfig.screenWidth / 2)
        self.tipViewText.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable)
        # tipViewText.setScale(1.5)
        self.tipViewText.setFont(QFont(self.font().family(), 20))
        self.graphicsScene.addItem(self.tipViewText)

        # for color in self.colorList:
        #     self.pIdAndColorList.append(f"000,{color}")
        # self.cycle00 = self.graphicsScene.addEllipse(0, 0, self.cycleRadius, self.cycleRadius)
        # my_pen = QPen()  # 实例QPen
        # my_pen.setColor(self.colorList[0])  # 设置颜色
        # self.cycle00.setPen(my_pen)
        # self.cycle00.setPos(0, 0)
        # self.cycle00.setVisible(False)

    def DrawQGraphicsPathXX(self, id_str):
        try:
            # 实例QPen
            self.my_pen = QPen()
            # 实例QGraphicsPathItem
            expr1 = f"self.QGraphicsPath{id_str} = QGraphicsPathItem()"
            # 场景添加图元
            expr2 = f"self.graphicsScene.addItem(self.QGraphicsPath{id_str})"
            exec(expr1)
            exec(expr2)
        except Exception as e:
            pass

    def DrawQPainterPathXX(self, ind_color, id_str, point_f, start=False):
        if start:
            try:
                # print("1 \t {} \t X: {}, Y:{}".format(id_str, point_f.x(), point_f.y()))
                # expr1 = f"self.cycle{id_str}.setVisible(True)"
                # expr2 = f"self.cycle{id_str}.setPos({pt.x() - self.cycleRadius / 2}, {pt.y() - self.cycleRadius / 2})"
                # 实例路径函数
                # self.path000 = QPainterPath()
                # self.path000.moveTo(point_f)
                expr1 = f"self.path{id_str} = QPainterPath()"
                # 路径开始于# 设置颜色
                expr2 = f"self.path{id_str}.moveTo(point_f)"
                exec(expr1)
                exec(expr2)
                self.DrawQGraphicsPathXX(id_str=id_str)
            except Exception as e:
                pass
                # print('Error 1:', e)
        try:
            # self.path000.lineTo(point_f)
            # self.QGraphicsPath000.setPath(self.path000)
            expr3 = f"self.path{id_str}.lineTo(point_f)  # 移动并连接点"
            # 设置颜色
            expr4 = f"self.my_pen.setColor(QColor(self.colorList[{ind_color}]))"
            # 设置宽度
            expr5 = f"self.my_pen.setWidth({self.pathPenWidth})"
            # 应用笔
            expr6 = f"self.QGraphicsPath{id_str}.setPen(self.my_pen)"
            expr7 = f"self.QGraphicsPath{id_str}.setPath(self.path{id_str})"
            # self.QGraphicsPath添加路径，如果写在上面的函数，是没线显示的，写在下面则在松键才出现线
            # self.QGraphicsPath00.moveBy(event.pos().x(),event.pos().y())
            exec(expr3)
            exec(expr4)
            exec(expr5)
            exec(expr6)
            exec(expr7)
            self.pathLength = 699.0 * (10 - ind_color)
            expr6 = f"self.DrawQPainterPathXX(ind_color=ind_color, id_str=id_str, point_f=point_f, start=True) if self.path{id_str}.length() > self.pathLength else None"
            exec(expr6)
            # expr7 = f"print('path {id_str} length :', self.path{id_str}.length())"
            # exec(expr7)
        except Exception as e:
            self.DrawQPainterPathXX(ind_color=ind_color, id_str=id_str, point_f=point_f, start=True)
            # print('Error 2:', e)

    def mousePressEvent(self, event):  # 重载鼠标事件
        if event.button() == Qt.LeftButton:  # 仅左键事件触发
            self.tipViewText.setText("鼠标事件")
            self.DrawQPainterPathXX(ind_color=0, id_str="000", point_f=event.pos(), start=True)

            # self.path00 = QPainterPath()  # 实例路径函数
            # self.path00.moveTo(event.pos())  # 路径开始于

            # # print('event.scenePos()', event.scenePos())
            # my_pen = QPen()  # 实例QPen
            # my_pen.setColor(self.colorList[0])  # 设置颜色
            # my_pen.setWidth(self.pathPenWidth)  # 设置宽度
            # self.QGraphicsPath00 = QGraphicsPathItem()  # 实例QGraphicsPathItem
            # self.QGraphicsPath00.setPen(my_pen)  # 应用笔
            # self.graphicsScene.addItem(self.QGraphicsPath00)  # 场景添加图元

    def mouseMoveEvent(self, event):  # 重载鼠标移动事件
        if event.buttons() & Qt.LeftButton:  # 仅左键时触发，event.button返回notbutton，需event.buttons()判断，这应是对象列表，用&判断
            self.DrawQPainterPathXX(ind_color=0, id_str="000", point_f=event.pos())
            # if self.path00:  # 判断self.path1
            #     # self.cycle00.setVisible(True)
            #     # self.cycle00.setPos(event.pos().x() - self.cycleRadius / 2, event.pos().y() - self.cycleRadius / 2)
            #     self.path00.lineTo(event.pos())  # 移动并连接点
            #     self.QGraphicsPath00.setPath(self.path00)  # self.QGraphicsPath添加路径，如果写在上面的函数，是没线显示的，写在下面则在松键才出现线
            #     # self.QGraphicsPath00.moveBy(event.pos().x(),event.pos().y())
            #     print("path length :", self.path00.length())

    def mouseReleaseEvent(self, event):  # 重载鼠标松开事件
        if event.button() == Qt.LeftButton:  # 判断左键松开
            pass
            # self.cycle00.setVisible(False)
            # if self.path00:
            #     self.path00.closeSubpath()  # 结束路径

    def viewportEvent(self, event: QEvent):  # real signature unknown; restored from __doc__
        """ viewportEvent(self, QEvent) -> bool """
        # // 处理touch事件
        QGraphicsView.viewportEvent(self, event)
        evType = event.type()
        # print(evType, '~' * 30)
        if evType == QEvent.TouchBegin or evType == QEvent.TouchUpdate or evType == QEvent.TouchEnd:
            touchEvent = QTouchEvent(event)
            # print('touchEvent', touchEvent)
            touchPoints = touchEvent.touchPoints()
            # print('touchPoints type', type(touchPoints)) 不可type
            # // 这里处理下，一般来说第一个点会被处理自动转换为鼠标
            # // 所以你需要添加一个bool的标识来在mouse事件处理时候
            # // 判断要不要处理
            id_x = 0
            tipText = f"点数：{str(len(touchPoints))} \n"
            # print("touchPoints LENS", len(touchPoints))
            for touchPoint in touchPoints:
                id_x += 1
                id_str = "%03d" % (touchPoint.id() % 1000)
                tipText += f" {id_str} "
                #  处理touch其实更多是对点状态的处理
                touchState = touchPoint.state()
                # print('touchPoint.state()', touchState)
                pt = touchPoint.pos()  # 获取鼠标坐标--view坐标
                # print('view坐标:{},{}'.format(pt.x(), pt.y()))
                # print("{} \t X: {}, Y:{}".format(id_str, pt.x(), pt.y()))
                if touchState == Qt.TouchPointPressed:
                    self.DrawQPainterPathXX(ind_color=id_x, id_str=id_str, point_f=pt, start=True)
                    # print('TouchPointPressed', touchState)
                elif touchState == Qt.TouchPointMoved:
                    try:
                        self.DrawQPainterPathXX(ind_color=id_x, id_str=id_str, point_f=pt)
                    except Exception as e:
                        pass
                    try:
                        expr4 = f"self.QGraphicsPath{id_str}.setPath(self.path{id_str}) if self.path{id_str} else None"
                        exec(expr4)
                    except Exception as e:
                        pass
                    # print('TouchPointMoved', touchState)
                elif touchState == Qt.TouchPointReleased:
                    pass
                    # print('TouchPointReleased', touchState)
            self.tipViewText.setText(tipText)
        # // 触摸结束
        if evType == QEvent.TouchEnd:
            pass
        return False

    def get_item_at_click(self, e):
        pos = e.pos()
        item = self.itemAt(pos)
        return item


if __name__ == '__main__':
    # QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
    QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
    # QApplication.setAttribute( Qt.AA_Use96Dpi)
    app = QApplication(sys.argv)
    font = QFont("宋体")
    pointsize = font.pointSize()
    font.setPixelSize(int(pointsize * 90 / 72))
    app.setFont(font)
    # myWin = MyMainWindow()
    w = MultiTouchWindow()
    # 首先设置接收触控事件
    # w.setAttribute(Qt.WA_AcceptTouchEvents, True)
    w.show()
    sys.exit(app.exec_())
